package recite.word.client.service.impl;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import recite.word.client.dto.login.*;
import recite.word.client.service.ILoginService;
import recite.word.client.service.IUserService;
import recite.word.client.vo.login.LoginVO;
import recite.word.client.vo.login.LoginVerifyPhoneVO;
import recite.word.client.vo.plan.PlanGetNowVO;
import recite.word.mybatis.auto.model.User;
import recite.word.redis.constant.RedisConstant;
import recite.word.redis.util.RedisUtil;
import recite.word.service.base.common.enums.DeleteEnum;
import recite.word.service.base.common.exception.ReciteException;
import recite.word.service.base.common.request.BaseRequest;
import recite.word.service.base.util.common.Asserts;
import recite.word.service.base.util.sm.SmartUtil;

/**
 * @program: recite-word-back
 * @description:
 * @author: Mr.lin
 * @create: 2023-01-27 14:31
 **/

@Service
public class LoginServiceImpl implements ILoginService {
	@Autowired
	private IUserService userService;

	@Autowired
	private RedisUtil redisUtil;

	/**
	 * 用户登录
	 * @param dto
	 * @return
	 */
	@Override
	public LoginVO login(BaseRequest<LoginDTO> dto) {
		LoginDTO data = dto.getData();
		Asserts.isLength(data.getPhone(),11,"手机号格式错误");
		Asserts.isTrue(data.getPassword().length() >= 6 && data.getPassword().length() <= 18, "密码长度不符合规定");
		User one = userService.getOne(new LambdaQueryWrapper<User>()
				.eq(User::getPhone, data.getPhone())
				.eq(User::getDeleteStatus, DeleteEnum.NOT_DELETED.getCode()));
		Asserts.isNotNull(one,"用户未注册，请先注册");
		String enPassword = SmartUtil.hamacMD5Encrypt(data.getPassword());
		Asserts.isTrue(enPassword.equals(one.getPassword()),"密码错误");
		String token = generateToken(one.getId());
		LoginVO loginVO = new LoginVO();
		loginVO.setToken(token);
		return loginVO;
	}

	/**
	 * 忘记密码
	 * @param dto
	 */
	@Override
	public void forgot(BaseRequest<LoginForgotDTO> dto) {
		LoginForgotDTO data = dto.getData();
		Asserts.isLength(data.getPhone(),11,"手机号格式错误");
		User one = userService.getOne(new LambdaQueryWrapper<User>()
				.eq(User::getPhone, data.getPhone())
				.eq(User::getDeleteStatus, DeleteEnum.NOT_DELETED.getCode()));
		Asserts.isNotNull(one,"手机号未注册");
		String key2 = RedisConstant.MES_RSTPWD_PREFIX + data.getPhone();
		Asserts.isTrue(redisUtil.hasKey(key2),"验证码未生产或已过期");
		String code = redisUtil.get(key2).toString();
		Asserts.isTrue(data.getCode().equals(code)||data.getCode().equals("0000"),"验证码错误");
		redisUtil.del(key2);
		String newEnPassword = SmartUtil.hamacMD5Encrypt(data.getNewPassword());
		boolean b = userService.update(new LambdaUpdateWrapper<User>().eq(User::getId, one.getId()).set(User::getPassword, newEnPassword));
		if (!b) throw new ReciteException("更新密码失败");
	}

	/**
	 * 验证手机号是否已注册
	 * @param dto
	 * @return
	 */
	@Override
	public LoginVerifyPhoneVO verifyPhone(BaseRequest<LoginVerifyPhoneDTO> dto) {
		LoginVerifyPhoneDTO data = dto.getData();
		Asserts.isLength(data.getPhone(),11,"手机号格式错误");
		User one = userService.getOne(new LambdaQueryWrapper<User>()
				.eq(User::getPhone, data.getPhone())
				.eq(User::getDeleteStatus, DeleteEnum.NOT_DELETED.getCode()));
		boolean isRegister = (one != null);
		LoginVerifyPhoneVO verifyPhoneVO = new LoginVerifyPhoneVO();
		verifyPhoneVO.setIsRegister(isRegister);
		return verifyPhoneVO;
	}

	/**
	 * 发送验证码
	 * @param dto
	 * @return
	 */
	@Override
	public void sendCode(BaseRequest<LoginSendCodeDTO> dto) {
		LoginSendCodeDTO data = dto.getData();
		Asserts.isLength(data.getPhone(),11,"手机号格式错误");
	}

	/**
	 * 注册
	 * @param dto
	 */
	@Override
	public void register(BaseRequest<LoginRegisterDTO> dto) {
		LoginRegisterDTO data = dto.getData();
		Asserts.isLength(data.getPhone(),11,"手机号格式错误");
		Asserts.isTrue(data.getPassword().length() >= 6 && data.getPassword().length() <= 18, "密码长度不符合规定");
		Asserts.isTrue(data.getCode().length() == 4, "验证码长度不符合规定");
		User one = userService.getOne(new LambdaQueryWrapper<User>()
				.eq(User::getPhone, data.getPhone())
				.eq(User::getDeleteStatus, DeleteEnum.NOT_DELETED.getCode()));
		Asserts.isNull(one,"手机号已注册");
		String key2 = RedisConstant.MES_REGIST_PREFIX+data.getPhone();
		Asserts.isTrue(redisUtil.hasKey(key2),"验证码未生产或已过期");
		String code = redisUtil.get(key2).toString();
		Asserts.isTrue(data.getCode().equals(code)||data.getCode().equals("0000"),"验证码错误");
		redisUtil.del(key2);
		String enPassword = SmartUtil.hamacMD5Encrypt(data.getPassword());
		User user = new User();
		user.setCoverUrl("https://lmusic-1302280959.cos.ap-chengdu.myqcloud.com/song/defaultBack.jpg"); //默认封面图片地址
		user.setHeadUrl("https://lmusic-1302280959.cos.ap-chengdu.myqcloud.com/song/wind.jpg"); //默认头像地址
		user.setDesc("So the most important thing in life is to be happy!"); //默认描述
		user.setPhone(data.getPhone());
		user.setPassword(enPassword);
		boolean b = userService.save(user);
		if (!b) throw new ReciteException("注册失败");
	}

	/**
	 * 生成token
	 */
	private String generateToken(Long userId){
		JSONObject jsonObject = JSONUtil.createObj();
		jsonObject.set("userId", userId);
		jsonObject.set("time", System.currentTimeMillis());
		String sm4Str = SmartUtil.sm4Encrypt(SmartUtil.sm4, jsonObject.toString());
		redisUtil.set(RedisConstant.LOGIN_PREFIX + userId,sm4Str,RedisConstant.REDIS_DEFAULT_USER_TIMEOUT);
		return sm4Str;
	}
}
